﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using EnvDTE80;

namespace BovespaDesignRules
{
    public sealed class Rule_RemoveEmptyMethods : BaseAddIn.Rules.BaseRuleAddIn
    {
        #region Constructor

        public Rule_RemoveEmptyMethods()
            : base("BovespaRemoveEmptyMethods", "BovespaDesignRules.BovespaDesignRules", typeof(Rule_RemoveEmptyMethods).Assembly)
        {
        }

        #endregion

        #region Protected Override Methods

        protected sealed override void Check(CodeFunction funcao, CodeNamespace namespaceElement, CodeClass2 classe)
        {
            EditPoint texto = funcao.StartPoint.CreateEditPoint();
            string metodo = texto.GetText(funcao.EndPoint);
            List<string> linhas;
            int index;

            if (funcao.FunctionKind != vsCMFunction.vsCMFunctionConstructor)
            {
                if (!metodo.Contains(" virtual ")
                    && !metodo.Contains(" abstract "))
                {
                    index = metodo.IndexOf('{');
                    if (index > -1)
                    {
                        metodo = Common.Rotinas.GetTextNoComent(metodo);
                        metodo = metodo.Substring(index);

                        linhas = LimpaMetodo(metodo);

                        if (linhas.Count == 2
                            && linhas[0] == "{"
                            && linhas[1] == "}")
                        {
                            GeraProblemaAddIn(funcao.StartPoint.Parent.Parent.FullName,
                                             funcao.StartPoint.Line,
                                             funcao.StartPoint.DisplayColumn,
                                             "RemoveEmptyMethodsResolution",
                                             classe.Name,
                                             funcao.Name,
                                             namespaceElement.Name);
                        }
                    }
                }
            }
        }

        protected sealed override void Check(CodeProperty propriedade, CodeNamespace namespaceElement, CodeClass2 classe)
        {
            EditPoint texto = propriedade.StartPoint.CreateEditPoint();
            string metodo = texto.GetText(propriedade.EndPoint);
            CodeFunction funcao;
            List<string> linhas;
            int index;

            if (!metodo.Contains(" virtual ")
                && !metodo.Contains(" abstract "))
            {
                if (propriedade.Setter != null)
                {
                    funcao = propriedade.Setter;
                    texto = funcao.StartPoint.CreateEditPoint();
                    metodo = texto.GetText(funcao.EndPoint);

                    index = metodo.IndexOf('{');
                    if (index > -1)
                    {
                        metodo = Common.Rotinas.GetTextNoComent(metodo);
                        metodo = metodo.Substring(index);

                        linhas = LimpaMetodo(metodo);

                        if (linhas.Count == 2
                            && linhas[0] == "{"
                            && linhas[1] == "}")
                        {
                            GeraProblemaAddIn(propriedade.StartPoint.Parent.Parent.FullName,
                                             propriedade.StartPoint.Line,
                                             propriedade.StartPoint.DisplayColumn,
                                             "RemoveEmptyPropertiesResolution",
                                             classe.Name,
                                             propriedade.Name,
                                             namespaceElement.Name);
                        }
                    }
                }
            }
        }

        #endregion

        #region Private Methods

        private List<string> LimpaMetodo(string texto)
        {
            List<string> linhas = new List<string>(texto.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));

            for (int i = linhas.Count - 1; i >= 0; i--)
            {
                linhas[i] = linhas[i].Trim();

                if (String.IsNullOrEmpty(linhas[i]))
                    linhas.RemoveAt(i);
            }

            if (linhas.Count == 1)
            {
                for (int i = linhas[0].Length - 1; i >= 0; i--)
                {
                    if (linhas[0][i] == '}')
                    {
                        linhas[0] = linhas[0].Insert(i, "\r\n");
                    }
                    else if (linhas[0][i] == '{')
                    {
                        linhas[0] = linhas[0].Insert(i + 1, "\r\n");
                    }
                }

                linhas = LimpaMetodo(linhas[0]);
            }

            return linhas;
        }

        #endregion
    }
}
